﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ComponentFactory.Krypton.Toolkit;
using UserSurface;
using ApplicationCore;
using System.Data.Linq;

namespace EnzymeLaborTool
{
    public partial class ProtocolFrm : KryptonForm
    {
        private Guid _newItemUId = new Guid("11111111-1111-1111-1111-111111111111");

        public ProtocolFrm()
        {
            InitializeComponent();
        }

        private MainSurface _surface;
        private EnzymeDBDataContext _dataContext;
        EnzymeView _currentEnzyme;
        public void Init(MainSurface ms, EnzymeView enzyme)
        {
            _surface = ms;
            _currentEnzyme = enzyme;
            _dataContext = ms.CurrentDataContext;
            this.Text += " for " + enzyme.Analyte;

            BindProtocol();
        }

        #region Binding
        private void protocolBindingSource_CurrentChanged(object sender, EventArgs e)
        {

            BindSettings();
        }

        private void BindProtocol()
        {
            var q = from x in _dataContext.ProtocolViews
                    where x.UId != Guid.Empty
                    where x.Enzyme_Fk == _currentEnzyme.UId
                    orderby x.Name
                    select x;

            //var p = from x in _dataContext.ProtocolViews
            //        where x.UId == Guid.Empty

            //        select x;

            //var s = p.Union(q);
            protocolBindingSource.DataSource = q;
        }

        private void BindSettings()
        {
            ProtocolView pv = protocolBindingSource.Current as ProtocolView;

            if (pv != null)
            {
                if (pv.UId == Guid.Empty)
                {
                    protocolDataGridView.ReadOnly = true;
                }
                else
                {
                    protocolDataGridView.ReadOnly = false;
                }

                _dataContext.Refresh(RefreshMode.OverwriteCurrentValues, _dataContext.ProtocolSettingViews);
                _dataContext.Refresh(RefreshMode.OverwriteCurrentValues, _dataContext.ParameterViews);
                
                var settedParams = _dataContext.ProtocolSettingViews.Where(x => x.ProtocolUId == pv.UId).Select(x => x.ParameterUId).ToList();

                var q = _dataContext.ProtocolSettingViews.Where(x => x.ProtocolUId == pv.UId).ToList();

                var missingParams = _dataContext.ParameterViews.Where(x=>!settedParams.Contains(x.UId)).ToList();

                List<ProtocolSettingView> temp = new List<ProtocolSettingView>();
                foreach (var x in missingParams)
                {
                    temp.Add(new ProtocolSettingView
                                    {
                                        ParameterUId = x.UId,
                                        ProtocolUId = default(Guid?),
                                        ParameterName = x.Name,
                                        ParameterDataType = x.Datatype,
                                        ParameterDescription = x.Description,
                                        ParameterUnit = x.Unit,
                                        ParameterIsSplitVariable = x.IsSplitVariable
                                    });
                }

                settingsBindingSource.DataSource = q.Union(from y in temp select y).OrderBy(x => x.ParameterName);
            }
            else
            {
                settingsBindingSource.DataSource = null;
            }
        }
        #endregion

        #region CRUD Protocol

        //toolbar initiated add-action
        private void protocolAddNewItem_Click(object sender, EventArgs e)
        {
            if (!protocolDataGridView.IsCurrentCellInEditMode)
            {
                protocolBindingSource.AddNew();
                protocolDataGridView.BeginEdit(true);
            }
        }

        //create a default Material for adding
        private void protocolBindingSource_AddingNew(object sender, AddingNewEventArgs e)
        {
            e.NewObject = new ProtocolView { UId = _newItemUId, Name = "NewProtocol", Enzyme_Fk = _currentEnzyme.UId };
        }

        //validate added or updated material data
        private void protocolDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (protocolDataGridView.IsCurrentCellInEditMode)
            {
                var pv = protocolDataGridView.Rows[e.RowIndex].DataBoundItem as ProtocolView;
                if (pv == null)
                {
                    return;
                }
                var check = _dataContext.ProtocolViews.SingleOrDefault(x => x.UId != pv.UId && x.Name.ToLower() == e.FormattedValue.ToString().ToLower().Trim()
                                                                      && x.Enzyme_Fk == _currentEnzyme.UId);
                if (check != null)
                {
                    protocolDataGridView.Rows[e.RowIndex].ErrorText = "A Protocol with this name already exist.";
                    e.Cancel = true;
                }
            }
        }

        //save added and updated material
        private void protocolDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            protocolDataGridView.Rows[e.RowIndex].ErrorText = null;
            ProtocolView mv = null;
            try
            {
                mv = protocolDataGridView.Rows[e.RowIndex].DataBoundItem as ProtocolView;
            }
            catch (IndexOutOfRangeException)
            {
                //handles case where new row is edited and then escape key is pressed to cancel the new row
            }


            if (mv != null)
            {
                if (mv.UId == _newItemUId)
                {
                    mv.UId = _surface.AddProtocol(mv.Name, mv.Enzyme_Fk);
                }
                else
                {
                    _surface.UpdateProtocol(mv.UId, mv.Name, mv.Description);
                }
            }
        }

        //toolbar initiated delete-action
        private void protocolDeleteItem_Click(object sender, EventArgs e)
        {
            ProtocolView mv = protocolBindingSource.Current as ProtocolView;
            if (ConfirmProtocolDelete(mv))
            {

                if (mv != null)
                {
                    _surface.DeleteProtocol(mv.UId);
                    protocolBindingSource.RemoveCurrent();
                }
            }
        }

        //gridview initiated delete-action
        private void protocolDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            var pv = e.Row.DataBoundItem as ProtocolView;
            e.Cancel = !ConfirmProtocolDelete(pv);
        }

        //delete material 
        private void protocolDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            var mv = e.Row.DataBoundItem as ProtocolView;
            if (mv != null)
            {
                _surface.DeleteProtocol(mv.UId);
            }
        }

        //request user confirmation for delete
        private bool ConfirmProtocolDelete(ProtocolView pv)
        {
            if (pv == null)
                return false;
            if (pv.UId == Guid.Empty)
            {
                MessageBox.Show("You can't delete the Default Protocol!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return MessageBox.Show("Are you sure you want to delete the current protocol? All activities using this protocol are loosing related information!", "Confirm protocol delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                == DialogResult.Yes;
        }

        //trigger protocol update if description is changed
        private void kryptonTextBox1_Validated(object sender, EventArgs e)
        {
            ProtocolView pv = protocolBindingSource.Current as ProtocolView;
            if (pv != null)
            {
                _surface.UpdateProtocol(pv.UId, pv.Name, pv.Description);
            }
        }

        //force validation and related acation before the form gets closed
        private void ProtocolFrm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.ValidateChildren(ValidationConstraints.Visible);
        }
        #endregion

        #region CRUD ProtocolSetting

        //validate added and updated data
        private void settingsDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (settingsDataGridView.IsCurrentCellInEditMode)
            {
                DataGridViewRow row = settingsDataGridView.Rows[e.RowIndex];
                var pv = row.DataBoundItem as ProtocolSettingView;
                if (pv == null)
                {
                    return;
                }
                if (pv.ParameterDataType == "NUMBER" && !string.IsNullOrEmpty(e.FormattedValue.ToString()))
                {
                    double temp;
                    if (!double.TryParse(e.FormattedValue.ToString(), out temp))
                    {
                        row.ErrorText = "The parameter is not a valid number or empty.";
                        e.Cancel = true;
                    }
                }
                if (pv.ParameterDataType == "BOOL" && !string.IsNullOrEmpty(e.FormattedValue.ToString()))
                {
                    bool temp;
                    if (!bool.TryParse(e.FormattedValue.ToString(), out temp))
                    {
                        row.ErrorText = "The parameter is not a valid boolean or empty.";
                        e.Cancel = true;
                    }
                }
            }
        }

        //trigger add, update and delete
        private void settingsDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow row = settingsDataGridView.Rows[e.RowIndex];
            ProtocolView pv = protocolBindingSource.Current as ProtocolView;
            row.ErrorText = null;
            var psv = row.DataBoundItem as ProtocolSettingView;
            if (!psv.ProtocolUId.HasValue && (!string.IsNullOrEmpty(psv.Value) || !string.IsNullOrEmpty(psv.SplitValue)))
            {
                //add
                _surface.AddSetting(pv.UId, psv.ParameterUId, psv.Value, psv.SplitValue);
                BindSettings();
            }
            if (psv.ProtocolUId.HasValue && (!string.IsNullOrEmpty(psv.Value) || !string.IsNullOrEmpty(psv.SplitValue)))
            {
                //update
                _surface.UpdateSetting(pv.UId, psv.ParameterUId, psv.Value, psv.SplitValue);
                BindSettings();
            }
            if (psv.ProtocolUId.HasValue && string.IsNullOrEmpty(psv.Value) && string.IsNullOrEmpty(psv.SplitValue))
            {
                //delete
                _surface.DeleteSetting(pv.UId, psv.ParameterUId);
                BindSettings();
            }
        }

        private void settingsDataGridView_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            if (e.ColumnIndex > -1 && e.RowIndex > -1 && dgv.Columns[e.ColumnIndex].DataPropertyName == "Value")
            {
                ProtocolSettingView psv = dgv.Rows[e.RowIndex].DataBoundItem as ProtocolSettingView;
                if (psv != null)
                {
                    e.ToolTipText = psv.ParameterDescription;
                }
            }
            else
            {
                e.ToolTipText = null;
            }
        }

        private void settingsDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            ProtocolSettingView psvCurrent = settingsBindingSource.Current as ProtocolSettingView;

            DataGridView dgv = sender as DataGridView;
            if (e.ColumnIndex > -1 && e.RowIndex > -1)
            {
                if (psvCurrent != null && dgv.Columns[e.ColumnIndex] == splitValueColumn)
                {
                    if (psvCurrent.ParameterIsSplitVariable && _currentEnzyme.Type == "Enzyme")
                    {
                        _oldCellBackColor = e.CellStyle.BackColor;
                        e.CellStyle.BackColor = _oldCellBackColor;
                    }
                    else
                    {
                        _oldCellBackColor = e.CellStyle.BackColor;
                        e.CellStyle.BackColor = Color.DarkGray;
                    }
                }

                ProtocolSettingView psv = dgv.Rows[e.RowIndex].DataBoundItem as ProtocolSettingView;
                if (psv != null)
                {
                    if (psv.ProtocolUId.HasValue)
                        e.CellStyle.ForeColor = Color.Black;
                    else
                        e.CellStyle.ForeColor = Color.Gray;
                }
            }
        }
        #endregion

        private void OnEditParameter(object sender, EventArgs e)
        {
            ParameterFrm pf = new ParameterFrm();
            pf.Init(this._surface);
            pf.ShowDialog(this);
            BindProtocol();
        }

        private void protocolDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            try
            {
                if (e.Value.ToString() == "~Default")
                {
                    e.CellStyle.ForeColor = Color.DarkGray;
                    e.CellStyle.Font = new Font(e.CellStyle.Font, FontStyle.Italic);
                }
            }
            catch (Exception) { }
        }

        Color _oldCellBackColor;

        private void settingsBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            ProtocolSettingView psv = settingsBindingSource.Current as ProtocolSettingView;
            if (psv != null)
            {
                if (psv.ParameterIsSplitVariable && _currentEnzyme.Type == "Enzyme")
                {
                    valueColumn.HeaderText = "BlankValue";
                    // splitValueColumn.CellTemplate.Style.BackColor = _oldCellBackColor;
                    splitValueColumn.ReadOnly = false;
                    settingsDataGridView.Refresh();
                }
                else
                {
                    valueColumn.HeaderText = "Value";
                    //  splitValueColumn.CellTemplate.Style.BackColor = Color.DarkGray;
                    //if (settingsDataGridView.CurrentCell.ColumnIndex == splitValueColumn.Index)
                    //    settingsDataGridView.CurrentCell = settingsDataGridView.Rows[settingsDataGridView.CurrentCell.RowIndex].Cells[splitValueColumn.Index - 1];

                    splitValueColumn.ReadOnly = true;
                    settingsDataGridView.Refresh();
                }
            }
        }
    }
}
